package ldh.im.fxgui.controller.sub;

import com.jfoenix.controls.JFXDialog;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.DirectoryChooser;
import javafx.stage.Popup;
import ldh.im.dto.base.OkResp;
import ldh.im.dto.business.message.MessageWithdrawReq;
import ldh.im.dto.enums.MessageType;
import ldh.im.fxbase.dao.ImMessageDao;
import ldh.im.fxbase.data.pojo.ImMessage;
import ldh.im.fxbase.data.pojo.status.ImMessageStatus;
import ldh.im.fxbase.richtext.ImTextArea;
import ldh.im.fxbase.rpc.service.RpcMessageService;
import ldh.im.fxbase.service.MessageService;
import ldh.im.fxbase.util.*;
import ldh.im.fxgui.component.message.MessageHandler;
import ldh.im.fxgui.handle.CollectHandler;
import ldh.im.fxbase.util.MessageUtil;
import ldh.im.fxgui.util.UiUtil;
import ldh.im.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.ResourceBundle;

public class ImUserMessagePopupController implements Initializable {

    private static final Logger LOGGER = LoggerFactory.getLogger(ImUserMessagePopupController.class);

    private ImMessage imMessage;
    private Popup popup;
    private MessageHandler messageHandler;

    @FXML private Button reSendBtn;
    @FXML private Button withdrawBtn;
    @FXML private Button copyBtn;
    @FXML private Button transferBtn;
    @FXML private Button collectBtn;
    @FXML private Button refBtn;
    @FXML private Button selectBtn;
    @FXML private Button openBtn;
    @FXML private Button saveAsBtn;
    @FXML private Button showOnDirBtn;
    @FXML private Button deleteBtn;

    private ImMessageDao imMessageDao = BeanFactory.getInstance().getBean(ImMessageDao.class);

    public void setMessage(ImMessage message) {
        this.imMessage = message;
        bindMessageInfo();

        if (!imMessage.isAttachFile()) {
            openBtn.setVisible(false);
            openBtn.setManaged(false);

            saveAsBtn.setVisible(false);
            saveAsBtn.setManaged(false);

            showOnDirBtn.setVisible(false);
            showOnDirBtn.setManaged(false);
        }
        if (imMessage.getMessageType() == MessageType.Audio) {
           showButtons(collectBtn, reSendBtn, selectBtn, refBtn, deleteBtn);
        }
    }

    public void rebuild() {
        bindMessageInfo();
    }

    public void setPopup(Popup popup) {
        this.popup = popup;
        popup.setUserData(this);
    }

    public void setMessageHandler(MessageHandler messageHandler) {
        this.messageHandler = messageHandler;
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {

    }

    @FXML
    private void copyMessage(ActionEvent actionEvent) {
        if (imMessage.getContent() == null) return;
        Clipboard clipboard = Clipboard.getSystemClipboard();
        ClipboardContent content = new ClipboardContent();
        if (imMessage.getMessageType() == MessageType.Image) {
            String imagePath = FileUtil.getFilePath(imMessage);
            Image image = new Image(imagePath);
            content.putImage(image);
        } else if (imMessage.isAttachFile()) {
            content.putFiles(Arrays.asList(new File(FileUtil.getFilePath(imMessage))));
        } else if (imMessage.getMessageType() == MessageType.RichText) {
            content.put(ImTextArea.IM_DATA_FORMAT, imMessage.getContent().toString());
        } else {
            content.putString(imMessage.getContent().toString());
        }
        clipboard.setContent(content);
        popup.hide();
    }

    @FXML
    private void transferMessage(ActionEvent actionEvent) {
        RegionUtil.FxmlBean<Pane, TransferMessageController> fxmlBean = RegionUtil.loadFxmlBean(this.getClass().getResource("/fxml/sub/TransferMessagePane.fxml"));
        StackPane dialogRoot = messageHandler.getDialogRoot();
        JFXDialog dialog = null;
        if (dialogRoot != null) {
            dialog = DialogUtil.show(dialogRoot, fxmlBean.getNode(), false);
        } else {
            dialog = DialogUtil.show(fxmlBean.getNode(), false);
        }

        fxmlBean.getController().setDialog(dialog);
        fxmlBean.getController().setTransferImages(Arrays.asList(imMessage), true);
        popup.hide();
    }

    @FXML
    private void collectMessage(ActionEvent actionEvent) {
        CollectHandler collectHandler = BeanFactory.getInstance().getBean(CollectHandler.class);
        collectHandler.collectMessage(messageHandler.getDialogRoot(), imMessage);
        popup.hide();
    }

    @FXML
    private void deleteMessage(ActionEvent actionEvent) {
        ThreadPoolUtil.submit(()->{
            try {
                imMessageDao.deleteMessage(imMessage.getId());
                FxThreadUtil.runLater(()->{
                    messageHandler.deleteMessage(imMessage);
                    DialogUtil.showSuccess(messageHandler.getDialogRoot(), "删除成功");
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        popup.hide();
    }

    @FXML
    private void reSendMessage(ActionEvent actionEvent) {
        if(imMessage.getStatus() != ImMessageStatus.created) {
            return;
        }
        ThreadPoolUtil.submit(()->{
            try {
                RpcMessageService rpcMessageService = RpcUtil.getRpcBootstrap().getRpcConfig().getClientBean(RpcMessageService.class);

                OkResp okResp = rpcMessageService.sendMessage(MessageUtil.toMessageObject(imMessage));
                FxThreadUtil.runLater(()->UiUtil.uiUpdateMessage(imMessage));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        popup.hide();
    }

    @FXML
    private void withdrawMessage(ActionEvent actionEvent) {
        Task<OkResp> okRespTask = ThreadPoolUtil.submitTask(new Task<OkResp>() {

            @Override
            protected OkResp call() throws Exception {
                RpcMessageService rpcMessageService = RpcUtil.getRpcBootstrap().getRpcConfig().getClientBean(RpcMessageService.class);

                MessageService messageService = BeanFactory.getInstance().getBean(MessageService.class);
                messageService.withdrawMessage(UiUtil.getLoginImUser().getUserId(), imMessage);

                String messageId = imMessage.getServerId();
                if (StringUtil.isNotBlank(messageId)) {
                    MessageWithdrawReq messageWithdrawReq = new MessageWithdrawReq();
                    messageWithdrawReq.setMessageIds(Sets.asSet(messageId));
                    OkResp okResp = rpcMessageService.sendWithdrawMessages(messageWithdrawReq);
                    messageService.withdrawedMessage(UiUtil.getLoginImUser().getUserId(), imMessage);
                    return okResp;
                }
                return new OkResp();
            }
        });
        okRespTask.setOnSucceeded(e->{
            UiUtil.uiUpdateMessage(imMessage);
            DialogUtil.showSuccess(messageHandler.getDialogRoot(), "撤回成功");
        });
        okRespTask.setOnFailed(e->{
            LOGGER.error("消息退回失败", e);
            DialogUtil.alert("失败", "消息退回失败");
        });
        popup.hide();
    }

    @FXML
    private void refMessage(ActionEvent actionEvent) {
        if (messageHandler == null) {
            LOGGER.warn("messageHandler is null, please init messageHandler");
            return;
        }
        if (imMessage.getServerId() == null) {
            DialogUtil.alert("警告", "消息还未发送成功，不能进行引用");
            return;
        }
        messageHandler.refMessage(imMessage);
        popup.hide();
    }

    @FXML
    private void selectMessage(ActionEvent actionEvent) {
        if (messageHandler == null) {
            LOGGER.warn("messageHandler is null, please init messageHandler");
            return;
        }
        messageHandler.messageSelectProperty().set(true);
        popup.hide();
    }

    @FXML
    private void open(ActionEvent actionEvent) {
        if (actionEvent != null) {
            UiUtil.getMainPopup().hide();
        }
        String path = FileUtil.getFilePath(imMessage);
        LOGGER.info("showDocument path: {}", path);
        StageUtil.getHostServices().showDocument(path);
    }

    @FXML
    private void saveAs(ActionEvent actionEvent) {
        DirectoryChooser directoryChooser = new DirectoryChooser();
        File dir = directoryChooser.showDialog(saveAsBtn.getScene().getWindow());
        if (dir == null) return;

        imMessage.initMessageExt();
        File newFile = new File(dir, imMessage.getMessageExt().getFileName());
        if (newFile.exists()) {
            DialogUtil.alert("提醒", "文件已存在");
            return;
        }
        ThreadPoolUtil.submit(()->{
            try {
                String fromPath = FileUtil.getFilePath(imMessage);
                Files.copy(Paths.get(fromPath), newFile.toPath());
            } catch (Exception e) {
                LOGGER.error("复制文件失败", e);
            }
        });
    }

    @FXML
    private void showOnDir(ActionEvent actionEvent) {
        ThreadPoolUtil.submit(()->{
            try {
                String path = FileUtil.getFilePath(imMessage);
                File file = new File(path);
                FileUtil.openFileDirCommand(file.getParent());
            } catch (Exception ee) {
                LOGGER.error("打开目录失败", ee);
            }

        });
    }

    private void bindMessageInfo() {
        String userId = UiUtil.getLoginImUser().getUserId();
        if (imMessage.isSender(userId) && DateUtil.hasExceededTime(imMessage.getCreateDateTime(), 2)) { // 两分钟内的消息能撤回
            withdrawBtn.setVisible(false);
            withdrawBtn.setManaged(false);
        } else {
            withdrawBtn.setVisible(true);
            withdrawBtn.setManaged(true);
        }

        if (imMessage.getStatus() == ImMessageStatus.created) {
            reSendBtn.setVisible(true);
            reSendBtn.setManaged(true);
        } else {
            reSendBtn.setVisible(false);
            reSendBtn.setManaged(false);
        }
    }

    private void showButtons(Button... buttons) {
        for (Button b : buttons) {
            b.setVisible(true);
            b.setManaged(true);
        }
    }

}
